Skip to content

feat(associations): MEDIC/CTD drug-indication section + enriched details modal (#1348) - #1352

Closed
kevinschaper wants to merge 2 commits into
mainfrom
feat/medic-ctd-treatment-associations
Closed

feat(associations): MEDIC/CTD drug-indication section + enriched details modal (#1348)#1352
kevinschaper wants to merge 2 commits into
mainfrom
feat/medic-ctd-treatment-associations

Conversation

@kevinschaper

Copy link
Copy Markdown
Member

Draft — implements #1348 (simplified scope).

What this does

  • Surfaces the drug-indication section. Completes and un-hides the biolink:ChemicalOrDrugOrTreatmentToDiseaseOrPhenotypicFeatureAssociation mapping (formerly the hidden "Medical Action" entry): subject ChemicalEntity, directional labels "Indications" (drug page) / "Treatments" (disease/phenotype page). MEDIC's treats edges now render as a section on Chemical/Disease/Phenotype pages.
  • Enriches the association details modal (SectionAssociationDetails.vue) to show all remaining non-transient fields: knowledge level, the nested retrieval-source provenance chain (MEDIC's infores:medic ← infores:dailymed/FDA "approving agency" nesting), aggregator knowledge source, original predicate, qualifiers, frequency data, FDA adverse event level, and negated.

Scope decisions

  • CTD is folded in upstream in the ingest by swapping CTD edges to the same association category — no monarch-app change needed, and no per-section predicate filter. (Tracked separately as a monarch-ingest task.)
  • No datamodel change / make model required.

Verification

  • Backend: association-counts parser/impl/query + mapping tests pass; fixtures updated ('Medical Action''Treatments').
  • Frontend: parseRetrievalSources unit-tested (nested chain, empty, malformed); vue-tsc clean; prettier/eslint clean.
  • Not yet visually confirmed in a browser — best checked on the deploy preview (beta runs the old backend, so the section is only visible with this backend change).

https://claude.ai/code/session_018c9UddtKsKtm35YNrxHWuL

Complete and un-hide the ChemicalOrDrugOrTreatmentToDiseaseOrPhenotypicFeature
association mapping (formerly the hidden "Medical Action" entry) so MEDIC
chemical->disease/phenotype "treats" edges render as a section: subject
ChemicalEntity, directional labels "Indications" (drug page) / "Treatments"
(disease/phenotype page). Update fixtures to the new label.

Phase 1 of #1348; CTD merge + predicate filter to follow.

Claude-Session: https://claude.ai/code/session_018c9UddtKsKtm35YNrxHWuL
…1348)

Enrich the association details modal (SectionAssociationDetails.vue) to surface
the fields it previously hid: knowledge level, the nested retrieval-source
provenance chain (e.g. MEDIC's infores:medic <- infores:dailymed/FDA),
aggregator knowledge source, original predicate, qualifiers, frequency data,
FDA adverse event level, and negated. Extract the sources JSON parsing into a
tested util (parseRetrievalSources).

Claude-Session: https://claude.ai/code/session_018c9UddtKsKtm35YNrxHWuL
@netlify

netlify Bot commented Jul 9, 2026

Copy link
Copy Markdown

Deploy Preview for monarch-app ready!

Name Link
🔨 Latest commit 2a26c41
🔍 Latest deploy log https://app.netlify.com/projects/monarch-app/deploys/6a4f0810c159f90008765168
😎 Deploy Preview https://deploy-preview-1352--monarch-app.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.17%. Comparing base (f28d52c) to head (2a26c41).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1352   +/-   ##
=======================================
  Coverage   83.17%   83.17%           
=======================================
  Files         126      126           
  Lines        6617     6617           
=======================================
  Hits         5504     5504           
  Misses       1113     1113           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@claude

claude Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review: MEDIC/CTD drug-indication section + enriched details modal (#1348)

Nice, focused PR — un-hiding the ChemicalOrDrugOrTreatmentToDiseaseOrPhenotypicFeatureAssociation section and filling out SectionAssociationDetails.vue is a clean way to surface data that was already flowing through the pipeline but hidden from users.

Overview

  • association_type_mappings.yaml: renames "Medical Action" → "Indications"/"Treatments" and fills in subject_category/object_category (previously omitted).
  • use-association-categories.ts: empties HIDDEN_CATEGORIES, un-hiding the section.
  • SectionAssociationDetails.vue: adds Knowledge Level, Provenance (via new retrievalSources.ts helper), Aggregator Knowledge Source, Original Predicate, Qualifiers, Frequency Data, FDA Adverse Event Level, and Negated detail blocks.
  • New frontend/src/util/retrievalSources.ts + unit tests for parsing the nested sources provenance chain.
  • Backend fixtures updated for the label rename.

Code quality / style

  • The Vue additions follow the file's existing conventions well: same AppDetail/AppFlex patterns, same v-if-to-hide idiom already used for supporting_text, icons already registered in global/icons.ts, and the new qualifierRows/hasFrequencyData computeds read cleanly.
  • retrievalSources.ts is a good example of defensive parsing (try/catch per entry, skips malformed data) with tests covering the nested-chain, empty, and malformed cases.
  • Minor nit: const HIDDEN_CATEGORIES = new Set<string>([]); — since it's always empty now, new Set<string>() (no array arg) reads a bit more clearly, though this is trivial.

Potential issues

  • object_category: "biolink:Disease" on the new mapping entry doesn't cover PhenotypicFeature. I traced how subject_category/object_category are consumed (AssociationTypeMappings.get_traversable_associations in association_type_utils.py, used by the entity-grid/traversable-associations/{entity_category} endpoint) — it does an exact-match against entity_category, so this association will never be surfaced as traversable when entity_category == "biolink:PhenotypicFeature". Today this looks harmless because that endpoint is only wired into PageGridPlayground.vue, not the live node pages — the actual "Treatments" section on Disease/Phenotype pages is driven by association_counts (Solr facet on real subject/object membership), which doesn't consult this field at all. But it's worth double-checking this is intentional (vs. just an oversight from generalizing to "Disease" as the object type), since the entity-grid feature seems to be actively under development and could start relying on this mapping soon.
  • The PR description flags this itself, but worth restating: parseRetrievalSources assumes each sources entry may be a JSON-encoded array (nested chain) or a single object — this is inferred/tested against a hand-built fixture, not confirmed against a real API response yet. Since sources: Optional[list[str]] has no documented shape in the backend model, it'd be good to sanity-check on the deploy preview that MEDIC/CTD records actually serialize this way before merging out of draft.

Performance
No concerns — the new modal fields are simple computed properties over already-fetched association data, no extra requests introduced.

Security
No concerns — no new user input surfaces, and the JSON.parse in retrievalSources.ts is wrapped in try/catch so malformed data can't throw uncaught, and Vue's template interpolation escapes rendered values by default.

Test coverage

  • Good frontend unit coverage for the new parseRetrievalSources helper (nested chain, empty, malformed).
  • Backend changes are covered only via fixture updates for the label rename (per the PR description, existing association-counts/mapping tests pass) — there's no new backend test asserting the "Indications"/"Treatments" mapping actually resolves correctly for a Chemical/Disease/Phenotype entity, which would help catch the object_category gap above if it ever becomes load-bearing.
  • As noted in the PR description, this hasn't been visually verified against a live backend yet (beta runs the old backend) — worth doing before taking it out of draft, especially for the nested provenance rendering.

Overall this looks solid and low-risk to merge once visually verified against the new backend. The object_category scoping is the only thing I'd flag as worth a second look, though it doesn't appear to affect current production behavior.

@kevinschaper

Copy link
Copy Markdown
Member Author

Superseded by #1357, which merges CTD in-app via the flexible section-matching enabler (#1355) instead of the single-category approach. Keeping the same modal-enrichment work (cherry-picked).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant